home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / pennmush.000 / pennmush-1.50-p8-linux.tar / pennmush / move.c < prev    next >
C/C++ Source or Header  |  1993-04-01  |  15KB  |  609 lines

  1. /* move.c */
  2.  
  3. #include "copyright.h"
  4. #include <ctype.h>
  5.  
  6. #include "config.h"
  7. #include "db.h"
  8. #include "interface.h"
  9. #include "match.h"
  10. #include "externs.h"
  11. #include "globals.h"
  12.  
  13. void enter_room();
  14.  
  15. void moveto(what, where)
  16.     dbref what;
  17.     dbref where;
  18. {
  19.   enter_room(what, where);
  20. }
  21.  
  22. void moveit(what, where)
  23.     dbref what;
  24.     dbref where;
  25. {
  26.   dbref loc, old;
  27.  
  28.   /* remove what from old loc */
  29.   if ((loc = old = Location(what)) != NOTHING) {
  30.     Contents(loc) = remove_first(Contents(loc), what);
  31.   }
  32.   /* test for special cases */
  33.   switch (where) {
  34.     case NOTHING:
  35.       Location(what) = NOTHING;
  36.       return;            /* NOTHING doesn't have contents */
  37.     case HOME:
  38.       where = Exits(what);    /* home */
  39.       safe_tel(what, where);
  40.       return;
  41.       /*NOTREACHED*/
  42.       break;
  43.   }
  44.  
  45.   /* now put what in where */
  46.   PUSH(what, Contents(where));
  47.  
  48.   Location(what) = where;
  49.   if ((where != NOTHING) && !Dark(where) && (old != where)) {
  50.       if (Hearer(what)) {
  51.       did_it(what, old, "LEAVE", NULL, "OLEAVE", "has left.",
  52.          "ALEAVE", old);
  53.       if(Typeof(where) != TYPE_ROOM)
  54.           did_it(what, where, NULL, NULL, "OXENTER", NULL, NULL, old);
  55.       if(Typeof(old) != TYPE_ROOM)
  56.           did_it(what, old, NULL, NULL, "OXLEAVE", NULL, NULL, where);
  57.       did_it(what, where, "ENTER", NULL, "OENTER", "has arrived.",
  58.          "AENTER", where);
  59.       } else {
  60.       /* non-listeners only trigger the actions not the messages */
  61.       did_it(what, old, NULL, NULL, NULL, NULL, "ALEAVE", old);
  62.       did_it(what, where, NULL, NULL, NULL, NULL, "AENTER", where);
  63.       }
  64.   }
  65.   did_it(what, what, "MOVE", NULL, "OMOVE", NULL, "AMOVE", where);
  66. }
  67.  
  68. #define Dropper(thing) (Hearer(thing) && Connected(Owner(thing)))
  69.  
  70. void send_contents(loc, dest)
  71.     dbref loc;
  72.     dbref dest;
  73. {
  74.   dbref first;
  75.   dbref rest;
  76.   first = Contents(loc);
  77.   Contents(loc) = NOTHING;
  78.  
  79.   /* blast locations of everything in list */
  80.   DOLIST(rest, first) {
  81.     Location(rest) = NOTHING;
  82.   }
  83.  
  84.   while (first != NOTHING) {
  85.     rest = Next(first);
  86.     if (Dropper(first)) {
  87.       Location(first) = loc;
  88.       PUSH(first, Contents(loc));
  89.     } else
  90.       enter_room(first, Sticky(first) ? HOME : dest);
  91.     first = rest;
  92.   }
  93.  
  94.   Contents(loc) = reverse(Contents(loc));
  95. }
  96.  
  97. void maybe_dropto(loc, dropto)
  98.     dbref loc;
  99.     dbref dropto;
  100. {
  101.   dbref thing;
  102.   if (loc == dropto)
  103.     return;            /* bizarre special case */
  104.   if (Typeof(loc) != TYPE_ROOM)
  105.     return;
  106.   /* check for players */
  107.   DOLIST(thing, Contents(loc)) {
  108.     if (Dropper(thing))
  109.       return;
  110.   }
  111.  
  112.   /* no players, send everything to the dropto */
  113.   send_contents(loc, dropto);
  114. }
  115.  
  116. void enter_room(player, loc)
  117.     dbref player;
  118.     dbref loc;
  119. {
  120.   dbref old;
  121.   dbref dropto;
  122.   static int deep = 0;
  123.   if (deep++ > 15) {
  124.     deep--;
  125.     return;
  126.   }
  127.  
  128.   if(player < 0 || player >= db_top) {
  129.     deep--;
  130.     return;
  131.   }
  132. #ifdef notdef
  133.   if (loc == NOTHING) {            /* death to -1 */
  134.       free_object(player);
  135.       deep--;
  136.       return;
  137.   }
  138.  
  139. #endif
  140.   /* check for room == HOME */
  141.   if (loc == HOME)
  142.     loc = Home(player);
  143.  
  144.   if ((Typeof(player) != TYPE_PLAYER) && (Typeof(player) != TYPE_THING)) {
  145.     fprintf(stderr, "ERROR: Non object moved!! %d\n", player);
  146.     fflush(stderr);
  147.     deep--;
  148.     return;
  149.   }
  150.   if (Typeof(loc) == TYPE_EXIT) {
  151.     fprintf(stderr, "ERROR: Attempt to move %d to exit %d\n", player, loc);
  152.     deep--;
  153.     return;
  154.   }
  155.  
  156.   /* get old location */
  157.   old = Location(player);
  158.  
  159.   /* go there */
  160.   moveit(player, loc);
  161.  
  162.   /* if old location has STICKY dropto, send stuff through it */
  163.  
  164.   if ((loc != old) && Dropper(player) &&
  165.       (old != NOTHING) && (Typeof(old) == TYPE_ROOM) &&
  166.       ((dropto = Location(old)) != NOTHING) && Sticky(old)) 
  167.     maybe_dropto(old, dropto);
  168.  
  169.  
  170.   /* autolook */
  171.   look_room(player, loc, 2);
  172.   deep--;
  173. }
  174.  
  175.  
  176. /* teleports player to location while removing items they shouldnt take */
  177. void safe_tel(player, dest)
  178.     dbref player;
  179.     dbref dest;
  180. {
  181.   dbref first;
  182.   dbref rest;
  183.   if (dest == HOME)
  184.     dest = Home(player);
  185.   if (Owner(Location(player)) == Owner(dest)) {
  186.     enter_room(player, dest);
  187.     return;
  188.   }
  189.   first = Contents(player);
  190.   Contents(player) = NOTHING;
  191.  
  192.   /* blast locations of everything in list */
  193.   DOLIST(rest, first) {
  194.     db[rest].location = NOTHING;
  195.   }
  196.  
  197.   while (first != NOTHING) {
  198.     rest = db[first].next;
  199.     /* if thing is ok to take then move to player else send home.
  200.      * thing is not okay to move if it's STICKY and its home is not
  201.      * the player.
  202.      */
  203.     if (!controls(player, first) && (Sticky(first) && (Home(first) != player)))
  204.       enter_room(first, HOME);
  205.     else {
  206.       PUSH(first, Contents(player));
  207.       db[first].location = player;
  208.     }
  209.     first = rest;
  210.   }
  211.   Contents(player) = reverse(Contents(player));
  212.   enter_room(player, dest);
  213. }
  214.  
  215. int can_move(player, direction)
  216.     dbref player;
  217.     const char *direction;
  218. {
  219.   if (!strcasecmp(direction, "home"))
  220.     return 1;
  221.  
  222.   /* otherwise match on exits */
  223.   init_match(player, direction, TYPE_EXIT);
  224.   match_exit();
  225.   return (last_match_result() != NOTHING);
  226. }
  227.  
  228. void do_move(player, direction, type)
  229.     dbref player;
  230.     const char *direction;
  231.     int type;   /* type 0 is normal, type 1 is global */
  232. {
  233.   dbref exit_m;
  234.   dbref loc;
  235.   if (!strcasecmp(direction, "home")) {
  236.     /* send him home */
  237.     /* but steal all his possessions */
  238.     if ((loc = Location(player)) != NOTHING && !Dark(player) && !Dark(loc)){
  239.       /* tell everybody else */
  240.       notify_except(Contents(loc), player,
  241.             tprintf("%s goes home.", db[player].name));
  242.     }
  243.     /* give the player the messages */
  244.     notify(player, "There's no place like home...");
  245.     notify(player, "There's no place like home...");
  246.     notify(player, "There's no place like home...");
  247.     safe_tel(player, HOME);
  248.   } else {
  249.     /* find the exit */
  250. #ifdef DO_GLOBALS
  251.     if (type == 1)
  252.       init_match_global_check_keys(player, direction, TYPE_EXIT);
  253.     else if (type == 2)
  254.       init_match_remote_check_keys(getzone(getloc(player)), direction, 
  255.                    TYPE_EXIT);
  256.     else
  257. #endif
  258.     init_match_check_keys(player, direction, TYPE_EXIT);
  259.     match_exit();
  260.     switch (exit_m = match_result()) {
  261.       case NOTHING:
  262.     /* try to force the object */
  263.     notify(player, "You can't go that way.");
  264.     break;
  265.       case AMBIGUOUS:
  266.     notify(player, "I don't know which way you mean!");
  267.     break;
  268.       default:
  269.     /* we got one */
  270.     /* check to see if we got through */
  271.     if (could_doit(player, exit_m)) {
  272.       /* special cases for home throughout */
  273.  
  274.       did_it(player, exit_m, "SUCCESS", NULL, "OSUCCESS", NULL, "ASUCCESS",
  275.          NOTHING);
  276.       if (db[exit_m].location == HOME)
  277.         did_it(player, exit_m, "DROP", NULL, "ODROP", NULL, "ADROP",
  278.            db[player].exits);
  279.       else
  280.         did_it(player, exit_m, "DROP", NULL, "ODROP", NULL, "ADROP",
  281.            db[exit_m].location);
  282.  
  283.       if (db[exit_m].location == HOME) {
  284.         enter_room(player, db[player].exits);
  285.         return;
  286.       }
  287.  
  288.       switch (Typeof(db[exit_m].location)) {
  289.         case TYPE_ROOM:
  290.           enter_room(player, db[exit_m].location);
  291.           break;
  292.         case TYPE_PLAYER:
  293.         case TYPE_THING:
  294.           {
  295. #ifdef DESTROY
  296.         if (db[db[exit_m].location].flags & GOING) {
  297.           notify(player, "You can't go that way.");
  298.           return;
  299.         }
  300. #endif
  301.         if (getloc(getloc(exit_m)) == NOTHING)
  302.           return;
  303.         safe_tel(player, db[exit_m].location);
  304.           }
  305.           break;
  306.         case TYPE_EXIT:
  307.           notify(player, "This feature coming soon.");
  308.           break;
  309.       }
  310.     } else
  311.       did_it(player, exit_m, "FAILURE", "You can't go that way.", 
  312.          "OFAILURE", NULL, "AFAILURE", NOTHING);
  313.     break;
  314.     }
  315.   }
  316. }
  317.  
  318. void do_get(player, what)
  319.     dbref player;
  320.     const char *what;
  321. {
  322.   dbref loc = Location(player);
  323.   dbref thing;
  324.   char tbuf1[BUFFER_LEN];
  325.  
  326.   if ((Typeof(loc) != TYPE_ROOM) && !(db[loc].flags & ENTER_OK) &&
  327.       !controls(player, loc)) {
  328.     notify(player, "Permission denied.");
  329.     return;
  330.   }
  331.  
  332.   init_match_check_keys(player, what, TYPE_THING);
  333.   match_neighbor();
  334.   if (Long_Fingers(player))
  335.     match_absolute();        /* the wizard has long fingers */
  336.   else
  337.     match_controlled_absolute();
  338.  
  339.   if (match_result() == NOTHING) {
  340.     /* take care of possessive get (stealing) */
  341.     thing = parse_match_possessive(player, what);
  342.     if (!GoodObject(thing)) {
  343.       notify(player, "I don't see that here.");
  344.       return;
  345.     }
  346.     /* to steal something, you have to be able to get it, and the
  347.      * object must be ENTER_OK and not locked against you.
  348.      */
  349.     if (could_doit(player,thing) && 
  350.     (Flags(Location(thing)) & ENTER_OK)  &&
  351.     eval_boolexp(player, db[Location(thing)].enterkey,
  352.              Location(thing), 0, ENTERLOCK)) {
  353.       notify(Location(thing), tprintf("%s was taken from you.", Name(thing)));
  354.       moveto(thing,player);
  355.       notify(thing, "Taken.");
  356.       sprintf(tbuf1, "takes %s.", db[thing].name);
  357.       did_it(player, thing, "SUCCESS", "Taken.", "OSUCCESS", tbuf1, "ASUCCESS",
  358.          NOTHING);
  359.     } else
  360.       did_it(player, thing, "FAILURE", "You can't take that from there.",
  361.          "OFAILURE", NULL, "AFAILURE", NOTHING);
  362.     return;
  363.   } else {
  364.     if ((thing = noisy_match_result()) != NOTHING) {
  365.       if (db[thing].location == player) {
  366.         notify(player, "You already have that!");
  367.         return;
  368.       }
  369.       switch (Typeof(thing)) {
  370.       case TYPE_PLAYER:
  371.       case TYPE_THING:
  372.     if (thing == player) {
  373.       notify(player, "You cannot get yourself!");
  374.       return;
  375.     }
  376.     if (could_doit(player, thing)) {
  377.       moveto(thing, player);
  378.       notify(thing, "Taken.");
  379.       sprintf(tbuf1, "takes %s.", db[thing].name);
  380.       did_it(player, thing, "SUCCESS", "Taken.", "OSUCCESS", tbuf1,
  381.          "ASUCCESS", NOTHING);
  382.     } else
  383.       did_it(player, thing, "FAILURE", "You can't pick that up.",
  384.          "OFAILURE", NULL, "AFAILURE", NOTHING);
  385.     break;
  386.       case TYPE_EXIT:
  387.     notify(player, "You can't pick up exits.");
  388.     return;
  389.       default:
  390.     notify(player, "You can't take that!");
  391.     break;
  392.       }
  393.     }
  394.   }
  395. }
  396.  
  397.  
  398. void do_drop(player, name)
  399.     dbref player;
  400.     const char *name;
  401. {
  402.   dbref loc;
  403.   dbref thing;
  404. #ifdef DESTROY
  405.   int reward;
  406. #endif
  407.   char tbuf1[BUFFER_LEN];
  408.  
  409.   if ((loc = getloc(player)) == NOTHING)
  410.     return;
  411.  
  412.   init_match(player, name, TYPE_THING);
  413.   match_possession();
  414.   match_controlled_absolute();
  415.  
  416.   switch (thing = match_result()) {
  417.     case NOTHING:
  418.       notify(player, "You don't have that!");
  419.       return;
  420.     case AMBIGUOUS:
  421.       notify(player, "I don't know which you mean!");
  422.       return;
  423.     default:
  424.       if (db[thing].location != player) {
  425.     /* Shouldn't ever happen. */
  426.     notify(player, "You can't drop that.");
  427.     return;
  428.       } else if (Typeof(thing) == TYPE_EXIT) {
  429.     notify(player, "Sorry you can't drop exits.");
  430.     return;
  431.       } else if (IS(loc, TYPE_ROOM, ROOM_TEMPLE)) {
  432.     /* sacrifice time */
  433. #ifdef DESTROY
  434.     if (Typeof(thing) == TYPE_PLAYER) {
  435.       notify(player, "Hey! No blood sacrifices please!.");
  436.       return;
  437.     }
  438.     if (Flags(thing) & SAFE) {
  439.       notify(player, 
  440.          "That object is marked SAFE and cannot be sacrificed.");
  441.       return;
  442.     }
  443.     /* Patched to destroy sacrificed objects */
  444.  
  445.     sprintf(tbuf1, "drops %s.", db[thing].name);
  446.     did_it(player, thing, "DROP", "Dropped.", "ODROP", tbuf1,
  447.            "ADROP", NOTHING);
  448.  
  449.     notify(player, tprintf("%s is consumed in a burst of flame!",
  450.                    db[thing].name));
  451. #ifdef FULL_INVIS
  452.     if(!Dark(player)) {
  453.       notify_except(Contents(loc), player,
  454.             tprintf("%s sacrifices %s.", db[player].name,
  455.                 db[thing].name));
  456.     } else {
  457.       notify_except(Contents(loc), player,
  458.             tprintf("Someone sacrifices %s.", db[thing].name));
  459.     }
  460. #else
  461.     notify_except(Contents(loc), player,
  462.               tprintf("%s sacrifices %s.", db[player].name,
  463.                    db[thing].name));
  464. #endif
  465.     /* check for reward */
  466.     if (!controls(player, thing) || (Typeof(player) != TYPE_PLAYER)) {
  467.       reward = Pennies(thing);
  468.       if (reward < 1 || (Pennies(db[player].owner) > MAX_PENNIES)) {
  469.         reward = 1;
  470.       } else if (reward > MAX_OBJECT_ENDOWMENT) {
  471.         reward = MAX_OBJECT_ENDOWMENT;
  472.       }
  473.       giveto(db[player].owner, reward);
  474.       notify(player, tprintf("You have received %d %s for your sacrifice.",
  475.                      reward, reward == 1 ? MONEY : MONIES));
  476.     }
  477.     /* do the actual destruction */
  478.     notify(thing, "You have been sacrificed.");
  479.     moveto(thing, NOTHING);
  480.     Toggles(thing) |= THING_DEST_OK;
  481.     do_destroy(player,tprintf("#%d",thing), 1);
  482.     return;
  483. #else
  484.     notify(player, "Sacrifices are not being accepted. Sorry.");
  485.     return;
  486. #endif
  487.       } else if (Sticky(thing)) {
  488.     notify(thing, "Dropped.");
  489.     safe_tel(thing, HOME);
  490.       } else if ((Location(loc) != NOTHING) && (Typeof(loc) == TYPE_ROOM) &&
  491.          !Sticky(loc)) {
  492.     /* location has immediate dropto */
  493.     notify(thing, "Dropped.");
  494.     moveto(thing, db[loc].location);
  495.       } else {
  496.     notify(thing, "Dropped.");
  497.     moveto(thing, loc);
  498.       }
  499.       break;
  500.   }
  501.   sprintf(tbuf1, "drops %s.", db[thing].name);
  502.   did_it(player, thing, "DROP", "Dropped.", "ODROP", tbuf1, "ADROP", NOTHING);
  503. }
  504.  
  505.  
  506. void do_enter(player, what, is_alias)
  507.      dbref player;
  508.      const char *what;
  509.      int is_alias;        /* 1 if we got here via enter alias */
  510. {
  511.   dbref thing;
  512.   init_match_check_keys(player, what, TYPE_THING);
  513.   match_neighbor();
  514.   match_exit();
  515.   if (is_alias || Hasprivs(player))
  516.     match_absolute();        /* necessary for enter aliases to work */
  517.  
  518.   if ((thing = noisy_match_result()) == NOTHING) {
  519.     /* notify(player,"I don't see that here.");   */
  520.     return;
  521.   }
  522.   switch (Typeof(thing)) {
  523.     case TYPE_ROOM:
  524.     case TYPE_EXIT:
  525.       notify(player, "Permission denied.");
  526.       break;
  527.     default:
  528.       /* the object must pass the lock. Also, the thing being entered */
  529.       /* has to be controlled, or must be enter_ok */
  530.       if (!(((Flags(thing) & ENTER_OK) || controls(player, thing)) &&
  531.       (eval_boolexp(player, db[thing].enterkey, thing, 0, ENTERLOCK)))) {
  532.     did_it(player, thing, "EFAIL", "Permission denied.", "OEFAIL",
  533.            NULL, "AEFAIL", NOTHING);
  534.     return;
  535.       }
  536.       if(thing == player) {
  537.     notify(player, "Sorry, you must remain beside yourself!");
  538.     return;
  539.       }
  540.       safe_tel(player, thing);
  541.       break;
  542.   }
  543. }
  544.  
  545. void do_leave(player)
  546.     dbref player;
  547. {
  548.   if (Typeof(Location(player)) == TYPE_ROOM) {
  549.     notify(player, "You can't leave");
  550.     return;
  551.   }
  552.   enter_room(player, db[Location(player)].location);
  553. }
  554.  
  555. #ifdef DO_GLOBALS
  556. dbref global_exit (player, direction)
  557.   dbref player;
  558.   const char *direction;
  559. {
  560.   init_match_global(player, direction, TYPE_EXIT);
  561.   match_exit();
  562.   return (last_match_result() != NOTHING);
  563. }
  564.  
  565. dbref remote_exit (loc, direction)
  566.      dbref loc;
  567.      const char *direction;
  568. {
  569.   init_match_remote(loc, direction, TYPE_EXIT);
  570.   match_remote();
  571.   return (last_match_result() != NOTHING);
  572. }
  573. #endif
  574.  
  575. #ifdef DO_GLOBALS
  576. void move_wrapper(player, command)
  577.      dbref player;
  578.      const char *command;
  579. {
  580.   /* check local exit, then zone exit, then global. If nothing is
  581.    * matched, treat it as local so player will get an error message.
  582.    */
  583.  
  584.   if (!Mobile(player))
  585.     return;
  586.  
  587.   if (can_move(player, command))
  588.     do_move(player, command, 0);
  589.   else if ((getzone(getloc(player)) != NOTHING) &&
  590.        remote_exit(getzone(getloc(player)), command))
  591.     do_move(player, command, 2);
  592.   else if ((getloc(player) != MASTER_ROOM) &&
  593.        global_exit(player, command))
  594.     do_move(player, command, 1);
  595.   else
  596.     do_move(player, command, 0);
  597. }
  598.  
  599. #else
  600.  
  601. void move_wrapper(player, command)
  602.      dbref player;
  603.      const char *command;
  604. {
  605.   do_move(player, command, 0);
  606. }
  607.  
  608. #endif                /* DO_GLOBALS */
  609.